Required Package

library(tidyverse)
library(ggthemes)
theme_set(theme_map())

Case: The Spatial Patterns of Conflict Data

Spatial data analysis on conflicts.

In this notebook, we explore the simpliest way to plot a global map visualizing the country-level frequencies of conflict severity.

Download UCDP Data

# Location: https://ucdp.uu.se/downloads/

download.file(
  "https://ucdp.uu.se/downloads/ged/ged221-csv.zip",
  destfile = "Lec_09/data/ged221-csv.zip")

# Decompress the downloaded ZIP file
unzip("Lec_09/data/ged221-csv.zip", exdir = "data")

# Codebook available on the website

Load the Conflict Data

d = read_csv("Lec_09/data/GEDEvent_v22_1.csv")
names(d)
##  [1] "id"                "relid"             "year"             
##  [4] "active_year"       "code_status"       "type_of_violence" 
##  [7] "conflict_dset_id"  "conflict_new_id"   "conflict_name"    
## [10] "dyad_dset_id"      "dyad_new_id"       "dyad_name"        
## [13] "side_a_dset_id"    "side_a_new_id"     "side_a"           
## [16] "side_b_dset_id"    "side_b_new_id"     "side_b"           
## [19] "number_of_sources" "source_article"    "source_office"    
## [22] "source_date"       "source_headline"   "source_original"  
## [25] "where_prec"        "where_coordinates" "where_description"
## [28] "adm_1"             "adm_2"             "latitude"         
## [31] "longitude"         "geom_wkt"          "priogrid_gid"     
## [34] "country"           "country_id"        "region"           
## [37] "event_clarity"     "date_prec"         "date_start"       
## [40] "date_end"          "deaths_a"          "deaths_b"         
## [43] "deaths_civilians"  "deaths_unknown"    "best"             
## [46] "high"              "low"               "gwnoa"            
## [49] "gwnob"

Plot Events on a Map

In our first task of spatial data analysis, we plot individual conflict events on a map

Create a dataframe named d_event_2021 that contains all events in the year of 2021

d_event_2021 = d |> filter(year == 2021)

Load the World Map

world = map_data("world")

names(world)
## [1] "long"      "lat"       "group"     "order"     "region"    "subregion"
# Summary statistics
summary(world)
##       long              lat              group            order       
##  Min.   :-180.00   Min.   :-85.192   Min.   :   1.0   Min.   :     1  
##  1st Qu.: -67.86   1st Qu.:  1.795   1st Qu.: 381.0   1st Qu.: 25215  
##  Median :  16.59   Median : 32.467   Median : 823.0   Median : 50492  
##  Mean   :  10.52   Mean   : 24.969   Mean   : 801.3   Mean   : 50470  
##  3rd Qu.:  78.95   3rd Qu.: 54.029   3rd Qu.:1243.0   3rd Qu.: 75746  
##  Max.   : 190.27   Max.   : 83.600   Max.   :1627.0   Max.   :100964  
##     region           subregion        
##  Length:99338       Length:99338      
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
## 
# Problem: Max. longitude > 180! Remove those
world = world |> filter(long <= 180)
world_china = world |> 
  filter(region == "China")

world_china |>
  ggplot() +
  geom_point(aes(x = long, y = lat))

Plot the world map

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  )

Add map projection: The earth is not a flat plane. When we draw maps, we “project” the non-flat plane to a 2D flat plane. There are multiple ways through which we can do this projection. For example:

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  coord_map()

There are a variety of projections available. You may choose what you like (for pragmatic and aethetic purposes.

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  coord_map("moll")

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  coord_map("gilbert")

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  coord_map("orth")

Plot Conflict Events as Points on the map

Let’s plot the events as points on the map.

ggplot() +
  geom_point(data = d_event_2021, aes(x = longitude, y = latitude))

Stack the points onto the map

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  # Below: Stack a layer onto the map
  geom_point(data = d_event_2021, aes(x = longitude, y = latitude)) +
  coord_map()

Make the Plot Prettier

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  geom_point(
    data = d_event_2021, 
    aes(x = longitude, y = latitude),
    alpha = 0.3
    ) +
  coord_map()

Plot Conflict Mortality

Use number of deaths as size of points.

First, we need to calculate total number of deaths

d_event_2021 = d_event_2021 |>
  mutate(Deaths = deaths_a + deaths_b + 
           deaths_civilians + deaths_unknown)

summary(d_event_2021$Deaths)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##    0.000    1.000    2.000    7.224    5.000 8355.000
d_event_2021 |>
  ggplot() +
  geom_density(aes(x = Deaths)) +
  theme_bw()

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", size = 0.1
  ) +
  geom_point(
    data = d_event_2021, 
    aes(x = longitude, y = latitude, size = Deaths),
    alpha = 0.3
    ) +
  coord_map() +
  theme(legend.position = "bottom")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

How to make the figure more informative? We start by taking logarithm of the Death variable. Apparently, the distribution of mortality is so skewed that we are not seeing meaning variations.

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  geom_point(
    data = d_event_2021, 
    aes(x = longitude, y = latitude, size = log(Deaths+1)),
    alpha = 0.1
    ) +
  coord_map() +
  theme(legend.position = "bottom")

# Q: Why log(Deaths**+1**) ?

Then, we use a more informative color scheme.

world |>
  ggplot(aes(x = long, y = lat)) +
  geom_map(
    map = world,
    aes(map_id = region),
    color = "white", fill = "gray", linewidth = 0.1
  ) +
  geom_point(
    data = d_event_2021, 
    aes(x = longitude, y = latitude, 
        size = log(Deaths+1), color = log(Deaths+1)),
    alpha = 0.1
    ) +
  scale_color_viridis_c(direction = -1, option = "A") +
  coord_map() +
  theme(legend.position = "bottom")

What we have drawn in this notebook are called “bubble maps” — for obvious reasons.

Exercise: Conflict in Africa

The current world map gives us an overview of conflicts in the world. What draws our attention is that Africa is an area where lots of conflict happen. As an after-class exercise, write code to plot a map of conflicts in Africa.

# YOUR CODE HERE